/*----------------------------------------------------------------------*
 *	CLASS:		Qt3Move
 *	Quantum Tic Tac Toe
 *	Copyright (c) 2004-2009 Novatia Labs, Inc.  All rights reserved.
 *----------------------------------------------------------------------*/

package com.novatialabs.qttt.engine.impl;

import com.novatialabs.qttt.engine.Qt3Player;
import com.novatialabs.qttt.engine.Qt3Square;

/**
 * Move keeps track of a move in a Quantum Tic Tac Toe game.
 *
 * @Author	John Levine
 * @Author	Duane Gibson
 * @Author Friendly development resources cheerfully provided by Charles Phares.
 * @Author	$Author$
 * @Version	$Revision$
 */

/*package*/ class Qt3Move
    extends Qt3Step
{

   /**
    * The game instance of which this move is a part.
    */
    // private final Qt3Game	game; // DRG TODO: really need this?

   /**
    * The player who chose the squares for this move (derived from the
    * moveNumber).
    */
    private final Qt3Player	player;

   /**
    * The index (0 to 8) of the first square chosen for this move.
    */
    private int			firstSquare;	// 0 to 8.

   /**
    * The index (0 to 8) of the second square chosen for this move.
    */
    private int			secondSquare;	// 0 to 8.


   /*-------------------------------------------------------------------*
    *	CONSTRUCTOR:	Qt3Move()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Sat Mar  6 13:30:36 PST 2004
    *-------------------------------------------------------------------*/
   /**
    * Constructs a move.
    */

    /*package*/ Qt3Move(
	    // Qt3Game	game,
	    int		moveNum,
	    Qt3Step	prevStep
	    )
    {
	super(moveNum, prevStep);

	// this.game = game;
	this.player = ((moveNum % 2) == 1)
		? Qt3Player.X
		: Qt3Player.O ;

    } // Qt3Move()

   /*-------------------------------------------------------------------*
    *	METHOD:		clearStep()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Sat Mar  6 14:19:17 PST 2004
    *-------------------------------------------------------------------*/
   /**
    * Clears this move object to an initial state.
    */

    protected void clearStep() {

	this.firstSquare = -1;
	this.secondSquare = -1;

    } // clearStep()

   /*-------------------------------------------------------------------*
    *	METHOD:		appendAsString()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Sat Mar  6 13:55:18 PST 2004
    *-------------------------------------------------------------------*/
   /**
    * Appends a representation of this object as a String to the specified
    * string buffer.
    *
    * @param	buf		string buffer to append to.
    * @param	resolution	the resolution associated with this move.
    */

    /*package*/ void appendAsString(
	StringBuffer	buf,
	Qt3Resolution	resolution
	)
    {

	buf.append(this.getMoveNumber());
	buf.append(": ");

	if ( this.firstSquare < 0 ) {
	    buf.append("   ");
	} else {
	    buf.append(this.firstSquare+1/*sqIndex->sqNum*/);

	    if ( this.secondSquare < 0 ) {
		buf.append("  ");
	    } else {
		resolution.appendAsString(buf);
		buf.append(this.secondSquare+1/*sqIndex->sqNum*/);
	    }

	}

    } // appendAsString()

   /*-------------------------------------------------------------------*
    *	METHOD:		getClassicalNotation()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Wed Feb  2 23:11:53 PST 2005
    *-------------------------------------------------------------------*/
   /**
    * Returns the classical notation for this move given the state of the
    * board.
    */

    /*package*/ String getClassicalNotation(
	Qt3Square[]	boardSquares
	)
    {

	final int moveNum = this.getMoveNumber();
	int squareIndex;

	// Classical boards are built using pending info.
	squareIndex = this.firstSquare;
	if ( boardSquares[squareIndex].getPendingOwningMove() == moveNum ) {
	    return Integer.toString(squareIndex + 1);
	}

	squareIndex = this.secondSquare;
	if ( boardSquares[squareIndex].getPendingOwningMove() == moveNum ) {
	    return Integer.toString(squareIndex + 1);
	}

	return "?";

    } // getClassicalNotation()

   /*-------------------------------------------------------------------*
    *	METHOD:		getPlayer()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Sat Mar  6 14:09:42 PST 2004
    *-------------------------------------------------------------------*/
   /**
    * Returns the player whose move this is.
    */

    public Qt3Player getPlayer() {
	return this.player;
    } // getPlayer()

   /*-------------------------------------------------------------------*
    *	METHOD:		getFirstSquareIndex()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Sat Mar  6 14:10:36 PST 2004
    *-------------------------------------------------------------------*/
   /**
    * Returns the index (0 to 8) of the first square chosen for this move
    * or -1 if the first square has not yet been chosen.
    */

    public int getFirstSquareIndex() {
	return this.firstSquare;
    } // getFirstSquareIndex()

   /*-------------------------------------------------------------------*
    *	METHOD:		setFirstSquareIndex()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Sat Mar  6 13:55:18 PST 2004
    *-------------------------------------------------------------------*/
   /**
    * Sets the first square for this move.
    */

    /*package*/ void setFirstSquareIndex( int squareIndex ) {

	if ( squareIndex < 0 || squareIndex > 8 ) {
	    throw new IllegalArgumentException("squareIndex " + squareIndex
		    + " must be 0..8");
	}

	if ( this.firstSquare != -1 ) {
	    throw new IllegalStateException();
	}

	this.firstSquare = squareIndex;

    } // setFirstSquareIndex()

   /*-------------------------------------------------------------------*
    *	METHOD:		getSecondSquareIndex()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Sat Mar  6 14:10:36 PST 2004
    *-------------------------------------------------------------------*/
   /**
    * Returns the index (0 to 8) of the second square chosen for this move
    * or -1 if the second square has not yet been chosen.
    */

    public int getSecondSquareIndex() {
	return this.secondSquare;
    } // getSecondSquareIndex()

   /*-------------------------------------------------------------------*
    *	METHOD:		setSecondSquareIndex()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Sat Mar  6 14:21:02 PST 2004
    *-------------------------------------------------------------------*/
   /**
    * Sets the second square for this move.
    */

    /*package*/ void setSecondSquareIndex( int squareIndex ) {

	if ( squareIndex < 0 || squareIndex > 8 ) {
	    throw new IllegalArgumentException("squareIndex " + squareIndex
		    + " must be 0..8");
	}

	if ( squareIndex == this.firstSquare ) {
	    throw new IllegalArgumentException(
		    "both moves may not be made in the same square");
	}

	if ( true // FUTURE: this.game.areMovesNormalized()
		&& (squareIndex < this.firstSquare) ) {
	    this.secondSquare = this.firstSquare;
	    this.firstSquare = squareIndex;
	} else {
	    this.secondSquare = squareIndex;
	}

    } // setSecondSquareIndex()

   /*-------------------------------------------------------------------*
    *	METHOD:		isRedoable()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Sat Jun  5 16:43:01 PDT 2004
    *-------------------------------------------------------------------*/
   /**
    * Returns whether this move can be "redone".
    */

    /*package*/ boolean isRedoable()
    {

	if ( (this.firstSquare != -1) && (this.secondSquare != -1) ) {
	    return true;
	}

	return false;

    } // isRedoable()

   /*-------------------------------------------------------------------*
    *	METHOD:		isAutomatic()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Sat Jun 19 17:42:27 PDT 2004
    *-------------------------------------------------------------------*/
   /**
    * Returns whether this step is "automatic".
    * This means that no user input is required, the completion of the step
    * is automatically implied by the state of the game.
    * Note that a step must be redo-able for it to be automatic.
    */

    /*package*/ boolean isAutomatic()
    {

	return false;

    } // isAutomatic()


   /*-------------------------------------------------------------------*
    *	METHOD:		getClassicalSquareIndex()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Sat Mar  6 15:18:33 PST 2004
    *-------------------------------------------------------------------*/
   /**
    * Returns the index (0 to 8) of this move's square in the resolved
    * classical game or -1 if this move is not yet resolved.
    */

    // DRG TODO: this belongs in a "step state" that is based on both the move and the resolution.
    // TODO: replaced by getClassicalNotation() ? 
    /*
    public int getClassicalSquareIndex() {

	switch ( this.resolution ) {

	    case Resolution_FIRST_SQUARE:
		return this.firstSquare;

	    case Resolution_SECOND_SQUARE:
		return this.secondSquare;

	    default:
	    case Resolution_NONE:
		return -1;
	}

    } // getClassicalSquareIndex()
    */

   /*-------------------------------------------------------------------*
    *	METHOD:		getOtherSquareIndex()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Sat Mar  6 14:56:02 PST 2004
    *-------------------------------------------------------------------*/
   /**
    * Returns the other square that this move is in.
    */

    /*package*/ int getOtherSquareIndex( int oneSquare ) {
	if ( this.firstSquare == oneSquare ) {
	    return this.secondSquare;
	} else if ( this.secondSquare == oneSquare ) {
	    return this.firstSquare;
	} else {
	    throw new IllegalArgumentException();
	}
    } // getOtherSquareIndex()

   /*-------------------------------------------------------------------*
    *	METHOD:		transformState()
    *	AUTHOR:		Duane Gibson
    *	CREATION DATE:	Wed Feb  2 23:33:05 PST 2005
    *-------------------------------------------------------------------*/
   /**
    * Returns a state object that consists of the given state modified by
    * the changes introduced by this step.
    */

    protected Qt3State transformState(
	Qt3State	prevState
	)
    {

	return new Qt3State(prevState, this.getMoveNumber(),
	       	this.firstSquare, this.secondSquare);

    } // transformState()

} // class Qt3Move

